home *** CD-ROM | disk | FTP | other *** search
/ Power Bytes: Money & Finance / PowerBytes Money and Finance CD-ROM 01 / PowerBytes Money and Finance CD-ROM 01.iso / Utilities / HFSOpen ƒ / HFSOpen.asm next >
Encoding:
Assembly Source File  |  1986-02-23  |  18.3 KB  |  875 lines  |  [TEXT/Anon]

  1. ; File HFSOpen.TXT
  2. ;--------------------------------------------------------------------
  3. ;
  4. ;     HFS Open Patch
  5. ;
  6. ;        written by Andy Hertzfeld  December 1985
  7. ;
  8. ;  This program installs an init resource that patches the open 
  9. ;  and OpenRF calls in the file system to work harder at opening a file.
  10. ;  It navigates the entire HFS catalog if a file isn't found,
  11. ;  only returning "File Not Found" if the file isn't in any
  12. ;  sub-directory.  It should let MDS and other programs work
  13. ;  more smoothly with HFS.
  14. ;
  15. ;--------------------------------------------------------------------
  16.  
  17. INCLUDE MacTraps.D
  18.  
  19. XDEF        START
  20.  
  21. ; I/O Equates
  22.  
  23. IOCompletion    EQU    12        ;offset to completion routine address
  24. IOResult    EQU    16        ;offset to I/O result
  25. IOFileName    EQU    18        ;offset to fileName
  26. IOVRefNum    EQU    22        ;offset to volume refNum
  27. IORefNum    EQU    24        ;offset to file refnum
  28.  
  29. IOFileType    EQU    26        ;offset to type byte, permissions
  30. IOMisc        EQU    28        ;offset to misc param
  31. IOBuffer    EQU    32        ;offset to buffer pointer
  32. IOByteCount    EQU    36        ;offset to count
  33. IONumDone    EQU    40        ;offset to number done
  34. IOPosMode    EQU    44        ;offset to positioning mode
  35. IOPosOffset    EQU    46        ;offset to position value
  36. IODirID        EQU    48        ;offset to directory ID
  37.  
  38. CSCode        EQU    26        ;control code offset
  39. CSParam        EQU    28        ;control parameter offset
  40.  
  41. ; low memory equates
  42.  
  43. KeyMap        EQU    $174        ;keyboard bitmap
  44. VCBQueue    EQU    $356        ;VCB Queue Header
  45. FCBSize        EQU    $3F6        ;new file system FCB size
  46. CurApRefNum    EQU    $900        ;our own refNum
  47.  
  48.  
  49. StartOfInit
  50.         BRA    InstallIt
  51.  
  52.  
  53.  
  54.  
  55.  
  56. ; first run the normal system open routine and see what kind of errors
  57. ; we get.
  58.  
  59. OpenPatch
  60.         PEA    BackFromOpen
  61.         MOVE.L    OldOpenAddr,-(SP)    ;invoke real open routine
  62.         RTS
  63.  
  64. ; we ran it so check out the errors
  65.  
  66. BackFromOpen
  67.         BEQ.S    DoneOpenPatch        ;if no errors, we're file
  68.         CMP.W    #-43,D0            ;file not found?
  69.         BNE.S    NormalOpen        ;if so, go to work
  70.  
  71. ; it was "file not found" so try to search the catalog
  72.  
  73.         MOVEQ    #0,D0            ;flag it's an open
  74.         BSR     SearchForFile
  75.  
  76. ; it's some other error so there's nothing we can do about it
  77.  
  78. NormalOpen
  79.         TST.W    D0            ;fix up condition codes
  80. DoneOpenPatch
  81.         RTS
  82.         
  83. ; OpenRF is handled the same as open
  84.  
  85. OpenRFPatch
  86.         PEA    BackFromOpenRF
  87.         MOVE.L    OldOpenRFAddr,-(SP)    ;invoke real open routine
  88.         RTS
  89.  
  90.  
  91. ; we ran it so check out the errors
  92.  
  93. BackFromOpenRF
  94.         BEQ.S    DoneOpenPatch        ;if no errors, we're file
  95.         CMP.W    #-43,D0            ;file not found?
  96.         BNE.S    NormalOpen        ;if so, go to work
  97.  
  98. ; it was "file not found" so try to search the catalog
  99.  
  100.         MOVEQ    #1,D0            ;flag it's an openRF
  101.         BSR     SearchForFile
  102.         BRA.S    NormalOpen
  103.                 
  104. ; GetFileInfo handler
  105.  
  106. GFIPatch
  107.         PEA    BackFromGFI
  108.         MOVE.L    GFIAddr,-(SP)    ;invoke real open routine
  109.         RTS
  110.  
  111. ; we ran it so check out the errors
  112.  
  113. BackFromGFI
  114.         BEQ.S    DoneGFIPatch        ;if no errors, we're file
  115.         CMP.W    #-43,D0            ;file not found?
  116.         BNE.S    NormalGFI        ;if so, go to work
  117.  
  118. ; if the name is NIL, give up
  119.  
  120.         TST.L    IOFileName(A0)
  121.         BEQ.S    NormalGFI
  122.  
  123.         MOVE.B    PatchOff,-(SP)        ;disabled?
  124.         TST.B    (SP)+
  125.         BNE.S    NormalGFI        ;if so, quit
  126.         
  127. ; it was "file not found" so try to search the catalog
  128.  
  129.         MOVEQ    #2,D0            ;flag it's a GetFileInfo
  130.         BSR     SearchForFile
  131.  
  132. ; it's some other error so there's nothing we can do about it
  133.  
  134. NormalGFI
  135.         TST.W    D0            ;fix up condition codes
  136.  
  137. DoneGFIPatch
  138.         RTS
  139.  
  140. ; Delete handler
  141.  
  142. DeletePatch
  143.         PEA    BackFromDelete
  144.         MOVE.L    DeleteAddr,-(SP)    ;invoke real open routine
  145.         RTS
  146.  
  147. ; we ran it so check out the errors
  148.  
  149. BackFromDelete
  150.         BEQ.S    DoneDeletePatch        ;if no errors, we're file
  151.         CMP.W    #-43,D0            ;file not found?
  152.         BNE.S    NormalDelete        ;if so, go to work
  153.  
  154. ; it was "file not found" so try to search the catalog
  155.  
  156.         MOVEQ    #3,D0            ;flag it's a Delete
  157.         BSR     SearchForFile
  158.  
  159. ; it's some other error so there's nothing we can do about it
  160.  
  161.  
  162. NormalDelete
  163.         TST.W    D0            ;fix up condition codes
  164. DoneDeletePatch
  165.         RTS
  166.  
  167. ; SetFileInfo handler
  168.  
  169. SFIPatch
  170.         PEA    BackFromSFI
  171.         MOVE.L    SFIAddr,-(SP)    ;invoke real open routine
  172.         RTS
  173.  
  174. ; we ran it so check out the errors
  175.  
  176. BackFromSFI
  177.         BEQ.S    DoneSFIPatch        ;if no errors, we're file
  178.         CMP.W    #-43,D0            ;file not found?
  179.         BNE.S    NormalSFI        ;if so, go to work
  180.  
  181. ; if the name is NIL, give up
  182.  
  183.         TST.L    IOFileName(A0)
  184.         BEQ.S    NormalSFI
  185.  
  186.         MOVE.B    PatchOff,-(SP)        ;disabled?
  187.         TST.B    (SP)+
  188.         BNE.S    NormalSFI        ;if so, quit
  189.         
  190. ; it was "file not found" so try to search the catalog
  191.  
  192.         MOVEQ    #5,D0            ;flag it's a SetFileInfo
  193.         BSR     SearchForFile
  194.  
  195. ; it's some other error so there's nothing we can do about it
  196.  
  197. NormalSFI
  198.         TST.W    D0            ;fix up condition codes
  199.  
  200. DoneSFIPatch
  201.         RTS
  202.  
  203. ; The CreatePatch is different from the others, since no search is
  204. ; involved.  If there is exactly one colon in the name, parse it
  205. ; and do the create into the proper subdirectory.  It's dangerous, so
  206. ; only do with option down
  207.  
  208. CreatePatch
  209.         BTST    #2,KeyMap+7
  210.         BEQ.S    OldCreate
  211.  
  212.         TST.W    FCBSize            ;new file system?            
  213.         BPL.S    HFSCreate        ;if so, skip
  214. OldCreate
  215.         MOVE.L    CreateAddr,-(SP)    ;handle normally
  216.         RTS
  217.  
  218. HFSCreate
  219.         MOVEQ    #4,D0            ;flags it's create
  220.  
  221. ; SearchForFile examines the file name, parses it into a name/vRefNum
  222. ; specification, searches the HFS catalog for a matching filename,
  223. ; and re-runs the call if it finds on.
  224.  
  225. SearchForFile
  226.         LINK    A6,#-258        ;allocate temp space
  227.         MOVEM.L    D2-D4/A0-A3,-(SP)    ;save work registers
  228.         MOVE.L    D1,-(SP)        ;keep D1 on top
  229.         
  230.         MOVE.W    D0,-258(A6)        ;remember Open/RF selector
  231.         MOVE.L    A0,A3            ;remember pBlock ptr
  232.  
  233.         TST.W    FCBSize            ;HFS installed?
  234.         BMI    SearchFailed        ;if not, give up
  235.         
  236.         MOVE.L    IOFileName(A3),A0    ;get name ptr
  237.         MOVEQ    #0,D0
  238.         MOVE.B    (A0)+,D0        ;get name size
  239.         
  240.         CMP.B    #':',(A0)        ;first character a colon?
  241.         BEQ    SearchFailed        ;if so, we failed
  242.  
  243. ; loop, searching for the colon
  244.  
  245. ScanForColon
  246.         CMP.B    #':',(A0)+        ;got a colon?
  247.         BEQ    FoundColon
  248.  
  249.  
  250.  
  251.         SUBQ    #1,D0            ;more to search?
  252.         BGT.S    ScanForColon        ;if so, keep looking
  253.  
  254. ; there wasn't a colon in the filename, so better no search, as it
  255. ; will really slow use down on those optional files.  Option key
  256. ; down and we will...
  257.  
  258.         BTST    #2,KeyMap+7
  259.         BEQ    SearchFailed
  260.  
  261.         MOVE.L    IOFileName(A3),A0    ;point to source
  262.         LEA    -256(A6),A1        ;name buffer
  263.         MOVEQ    #0,D0
  264.         MOVE.B    (A0),D0
  265.         ADDQ    #1,D0
  266.         _BlockMove            ;move in the name
  267.                                 
  268.         MOVE.W    IOVRefNum(A3),D3    ;get the VRefNum
  269.         
  270. ; OK, now search the HFS catalog, looking for the filename at -256(A6)
  271. ; on the volume whose vRefNum is in D3.  Also, handle create mode
  272. ; specially
  273.  
  274.  
  275. DoTheSearch
  276.         CMP.W    #4,-258(A6)        ;create mode?
  277.         BEQ.S    DoCreate        ;if so, handle specially
  278.         
  279.         LEA    PatchOff,A0
  280.         ST    (A0)            ;GFI patch off!
  281.         
  282.         MOVE.L    LastDirID,D0        ;get last directory ID
  283.         BEQ    SearchFromRoot        ;skip 1st search
  284.  
  285.         SUBQ    #4,SP            ;make room for result
  286.         MOVE.W    D3,-(SP)        ;push the vRefNum        
  287.         MOVE.L    D0,-(SP)        ;start at the root
  288.         PEA    -256(A6)        ;push file name
  289.         BSR    SearchCatalog
  290.         MOVE.L    (SP)+,D0        ;get the result
  291.         BEQ    SearchFromRoot        ;if not found, we failed
  292.  
  293. ; OK, we found the filename in a sub-directory, so open it as a
  294. ; working directory
  295.  
  296. FoundIt        
  297.         LEA    PatchOff,A0
  298.         CLR.B    (A0)            ;back on again
  299.         
  300.         LEA    LastDirID,A0        ;point to dirID variable
  301.         MOVE.L    D0,(A0)            ;update variable
  302.         
  303.         SUB.W    #80,SP
  304.         MOVE.L    SP,A0
  305.         CLR.L    IOFileName(A0)
  306.         MOVE.W    D3,IOVRefNum(A0)    ;set up vRefNum
  307.         MOVE.L    #'PTCH',28(A0)        ;set up proc ID
  308.  
  309.         MOVE.L    D0,48(A0)        ;set up dir ID
  310.  
  311.         MOVEQ    #1,D0            ;OpenWD trap
  312.         DC.W    $A260            ;new file system call
  313.         
  314.         MOVE.W    IOVRefNum(A0),D3    ;remember path refNum
  315.         ADD.W    #80,SP
  316.  
  317. ; now retry the trap, using the new vRefNum/name
  318.  
  319.         MOVE.L    (SP),D1            ;recover D1
  320.  
  321.         
  322.  
  323.         MOVE.L    IOFileName(A3),-(SP)    ;save old filename
  324.         MOVE.W    IOVRefNum(A3),-(SP)    ;save old vRefNum
  325.  
  326.         LEA    -256(A6),A1        ;get name pointer
  327.         MOVE.L    A1,IOFileName(A3)    ;save as the filename
  328.         MOVE.W    D3,IOVRefNum(A3)
  329.         MOVE.L    A3,A0
  330.  
  331.         PEA    DoneSearch1        ;push return address
  332.  
  333. ; compute the trap address using the table
  334.  
  335.         MOVE.W    -258(A6),D0        ;get switch value
  336.         ASL.W    #2,D0            ;multiply by 4
  337.         MOVE.L    OldOpenAddr(D0),-(SP)    ;push address
  338.         RTS                ;go do it
  339.  
  340. ; DoCreate does a special create using the parsed file name and
  341. ; lastDirID.  Don't do it if we find 2 colons in the name, though
  342.  
  343. DoCreate
  344.         MOVE.L    IOFileName(A3),A0    ;get name ptr
  345.         MOVEQ    #0,D0            ;clear length
  346.         MOVEQ    #0,D1            ;clear counter
  347.         MOVE.B    (A0)+,D0        ;get length
  348. CntColLoop
  349.  
  350.         CMP.B    #':',(A0)+        ;a colon?
  351.         BNE.S    @0
  352.  
  353.         ADDQ    #1,D1            ;count it
  354. @0
  355.         SUBQ    #1,D0
  356.         BGT.S    CntColLoop
  357.  
  358.         SUBQ    #1,D1            ;exactly one colon?
  359.         BNE     SearchFailed        ;if not, don't proceed
  360.  
  361. ; do a special create call, using lastDirID
  362.  
  363.         MOVE.L    LastDirID,D0
  364.  
  365.         BEQ    SearchFailed        ;make sure there is one
  366.         
  367.         SUB.W    #80,SP
  368.         MOVE.L    SP,A0
  369.  
  370.         LEA    -256(A6),A1
  371.         MOVE.L    A1,IOFileName(A0)    ;use parsed name
  372.         MOVE.W    D3,IOVRefNum(A0)    ;use vRefNum
  373.         MOVE.L    LastDirID,IODirID(A0)
  374.         CLR.W    IOFileType(A0)
  375.         CLR.L    IOMisc(A0)
  376.         
  377.         MOVE.W    #$A208,D1        ;flag it's HCreate
  378.  
  379.         PEA    BackFromCreate        ;we're done
  380.         MOVE.L    CreateAddr,-(SP)    ;push address
  381.         RTS                ;invoke it
  382.  
  383. BackFromCreate
  384.         ADD.W    #80,SP            ;pop off pBlock
  385.         BRA    DoneSearchFile        ;all done
  386.                         
  387. ; addresses of the normal receivers for the five patched out routines
  388.  
  389. OldOpenAddr
  390.         DC.W    0,0
  391. OldOpenRFAddr
  392.         DC.W    0,0
  393. GFIAddr
  394.         DC.W    0,0
  395. DeleteAddr
  396.         DC.W    0,0
  397. CreateAddr
  398.         DC.W    0,0
  399. SFIAddr
  400.         DC.W    0,0
  401. PatchOff
  402.         DC.W    0
  403.                                 
  404. ; all done, so return the result in D0
  405.  
  406. DoneSearch1
  407.         MOVE.W    (SP)+,IOVRefNum(A3)
  408.         MOVE.L    (SP)+,IOFileName(A3)
  409. DoneSearchFile
  410.         LEA    PatchOff,A0
  411.         CLR.B    (A0)
  412.  
  413.         MOVE.L    (SP)+,D1
  414.         MOVEM.L    (SP)+,D2-D4/A0-A3    ;restore registers
  415.         UNLK    A6            ;de-allocate locals
  416.  
  417.  
  418.         TST.W    D0
  419.  
  420.         RTS                ;all done!
  421.  
  422. ; handle the case where the search failed, returning "File not Found"
  423. ; special case create
  424.  
  425. SearchFailed
  426.         CMP.W    #4,-258(A6)        ;create mode?
  427.         BEQ.S    @0            ;if so, handle specially
  428.         
  429.         MOVEQ    #-43,D0            ;return file not found
  430.         BRA.S    DoneSearchFile
  431. @0
  432.         MOVE.L    (SP)+,D1
  433.         MOVEM.L    (SP)+,D2-D4/A0-A3
  434.         UNLK    A6
  435.         BRA    OldCreate
  436.                         
  437. ; we couldn't find it starting from the last one, so search from the root
  438.  
  439. SearchFromRoot
  440.         MOVE.L    LastDirID,D0        ;get last directory
  441.  
  442.         SUBQ.L    #2,D0            ;was it the root?
  443.         BEQ.S    SearchFailed        ;if so, don't do it twice
  444.         
  445.         SUBQ    #4,SP            ;make room for result
  446.         MOVE.W    D3,-(SP)        ;push the vRefNum        
  447.         MOVE.L    #2,-(SP)        ;start at the root
  448.         PEA    -256(A6)        ;push file name
  449.         BSR    SearchCatalog
  450.         MOVE.L    (SP)+,D0        ;get the result
  451.         BNE    FoundIt            ;if we're lucky we found it
  452.         BRA.S    SearchFailed
  453.  
  454. LastDirID
  455.         DC.L    0            ;directory from last time
  456.         
  457. ; FoundColon handles the case when the passed in name has a colon in it
  458. ; Use the part up to the colon to determine the vRefNum, and the part
  459. ; after the colon as the file name
  460.  
  461. FoundColon
  462.         LEA    -256(A6),A1        ;destination
  463.         SUBQ    #1,D0            ;adjust size
  464.         MOVE.B    D0,(A1)+        ;length byte
  465.         _BlockMove            ;move in the rest
  466.  
  467. ; now compute the length of the volume name in D1 and try to find
  468. ; it in the VCB queue
  469.  
  470.         MOVEQ    #0,D0
  471.         MOVE.L    IOFileName(A3),A1    ;point to beginning of name
  472.         SUB.L    A1,A0            ;compute size
  473.         MOVE.L    A0,D1            ;get size
  474.  
  475.         ADDQ.L    #1,A1            ;point at first char
  476.         SUBQ.L    #2,D1            ;adjust it
  477.         BLE.S    SearchFailed        ;skip if bad spec
  478.  
  479. ; now fly through the VCB queue, comparing against the name
  480.  
  481.         MOVE.L    VCBQueue+2,D0        ;get first volume ptr
  482.         BEQ.S    SearchFailed
  483. VCBSearchLoop
  484.         MOVE.L    D0,A2
  485.         LEA    $2C(A2),A0        ;point to volName
  486.  
  487.         MOVEQ    #0,D0
  488.         MOVE.B    (A0)+,D0        ;get length, point at 1st char
  489.         SWAP    D0
  490.         MOVE.W    D1,D0
  491.         _CmpString            ;compare with string in A1
  492.         BEQ.S    FoundTheVol
  493.  
  494.         MOVE.L    (A2),D0
  495.         BNE.S    VCBSearchLoop
  496.  
  497.         BRA    SearchFailed                                        
  498.  
  499. ; we found the volume.  The name is already at -256(A6) so get the
  500. ; vRefNum in D3 and dive back in
  501.  
  502. FoundTheVol
  503.         MOVE.W    78(A2),D3        ;get the vRefNum
  504.         BRA    DoTheSearch        
  505.  
  506.  
  507. ; FUNCTION SearchCatalog(vRefNum:INTEGER; curDir: LongInt; fName: Str255):LongInt
  508.  
  509. ;
  510. ;    SearchCatalog searches an HFS volume or sub-directory for a file with 
  511. ; a given name   It returns the directory ID of the directory
  512. ; holding the file, or 0 if it couldn't be found.  
  513.  
  514.  
  515. SearchCatalog
  516.         LINK    A6,#-108        ;allocate pBlock
  517.         CLR.L    18(A6)            ;set result to 0
  518.  
  519. ; better make sure we're running the new file system
  520.  
  521.         TST.W    FCBSize            ;for now, check new ROM
  522.         BMI    DoneSCatalog        ;if not, we're done
  523.         
  524. ; first do a file-name specific HGetFileInfo to see if the file is in
  525. ; the directory.
  526.  
  527.  
  528.  
  529.         LEA    -108(A6),A0        ;point A0 at pBlock
  530.         LEA    8(A6),A1        ;point at parameters
  531.         
  532.         MOVE.L    (A1)+,IOFileName(A0)    ;set up the name
  533.         MOVE.L    (A1)+,IODirID(A0)    ;set up directory ID
  534.         MOVE.W    (A1)+,IOVRefNum(A0)    ;set up vRefNum
  535.         CLR.W    IOMisc(A0)        ;clear type and index
  536.  
  537.         MOVE.L    12(A6),D1        ;get this dirID in D1
  538.         DC.W    $A20C            ;HGetFileInfo
  539.         BEQ.S    SCGotIt            ;if found, skip
  540.  
  541. ; it's not in the current directory, so index through all nodes to 
  542. ; recursively explore the sub-directories
  543.  
  544. CheckSubdirs
  545.  
  546.         CLR.L    IOFileName(A0)        ;don't want the name back
  547.         MOVE.W    #1,IOMisc(A0)        ;start with the first one
  548. SCatLoop
  549.         LEA    -108(A6),A0        ;point to the pBlock
  550.         MOVE.L    12(A6),IODirID(A0)    ;re-establish directory ID
  551.         
  552.         MOVEQ    #9,D0            ;HGetCatInfo call
  553.         DC.W    $A260            ;invoke HFS
  554.         BNE.S    DoneSCatalog        ;on error, give up
  555.         
  556. ; check if the current node is a directory
  557.  
  558.         BTST    #4,30(A0)        ;a directory?
  559.         BNE.S    CallSCAgain        ;if so, go handle it
  560.  
  561. ; keep looping until we've inspected them all
  562.  
  563. NextSCatalog
  564.         ADDQ.W    #1,IOMisc(A0)        ;bump the index
  565.         BRA.S    SCatLoop        ;loop until error
  566.         
  567. ; the current node is a directory, so call ourselves recursively to
  568. ; deal with it
  569.  
  570. CallSCAgain
  571.         SUBQ    #4,SP            ;make room for result
  572.         MOVE.W    16(A6),-(SP)        ;same vRefNum
  573.  
  574.         MOVE.L    IODirID(A0),-(SP)    ;new directory ID
  575.         MOVE.L    8(A6),-(SP)        ;same file name
  576.         BSR    SearchCatalog        ;call ourselves
  577.         
  578.         LEA    -108(A6),A0        ;re-establish A0
  579.         MOVE.L    (SP)+,D1        ;get directory ID
  580.         BEQ.S    NextSCatalog        ;if none, skip
  581.         
  582. ; we found it and D1 has the directory ID
  583.  
  584. SCGotIt
  585.         MOVE.L    D1,18(A6)        ;return the result
  586. DoneSCatalog
  587.         UNLK    A6
  588.         
  589.         MOVE.L    (SP)+,A0
  590.         ADD.W    #10,SP            ;strip parameters
  591.         JMP    (A0)
  592.         
  593. ; InstallIt is the routine that installs the above in the system heap
  594.  
  595.  
  596. InstallIt
  597.  
  598.         MOVEM.L    A2-A3,-(SP)
  599.         
  600.         LEA    OldOpenAddr,A1        ;point to saved address table
  601.         LEA    PatchNumbers,A2        ;point to traps to patch
  602.         LEA    PatchAddresses,A3
  603.                 
  604.         MOVE.W    (A2)+,D2        ;get # to do                
  605. InstallLoop
  606.         MOVE.W    (A2),D0
  607.         _GetTrapAddress
  608.  
  609.         MOVE.L    A0,(A1)+        ;save old address
  610.  
  611.         LEA    StartOfInit,A0        ;get base address
  612.         ADD.W    (A3)+,A0        ;compute address
  613.         MOVE.W    (A2)+,D0        ;get trap number
  614.         _SetTrapAddress
  615.  
  616.         DBRA    D2,InstallLoop
  617.  
  618.         MOVEM.L    (SP)+,A2-A3        
  619.         RTS
  620.  
  621. PatchNumbers
  622.         DC.W    5            ;6 patches to do
  623.         DC.W    0,10,12,9,8,13
  624. PatchAddresses
  625.         DC.W    OpenPatch-StartOfInit
  626.         DC.W    OpenRFPatch-StartOfInit
  627.         DC.W    GFIPatch-StartOfInit
  628.         DC.W    DeletePatch-StartOfInit
  629.         DC.W    CreatePatch-StartOfInit
  630.         DC.W    SFIPatch-StartOfInit                
  631. ;-------------------------------------------------------------------------
  632. ;
  633. ;  Here is the code that isn't part of the INIT resource.  It receives
  634. ;  control when the application is run and installs the Init resource
  635. ;  in the system resource file.
  636. ;
  637.  
  638. ;--------------------------------------------------------------------------
  639.  
  640. Start
  641.  
  642. ; first allocate some zeroed space by clearing it off the stack
  643.  
  644.         MOVE    #511,D0        ;need about 2K bytes
  645. ClearLoop
  646.         CLR.L    -(SP)
  647.         DBRA    D0,ClearLoop
  648.         
  649. ; initialize QuickDraw and the toolBox
  650.  
  651. InitWorld
  652.         PEA    -4(A5)        ;push address of QuickDraw vars
  653.         _InitGraf              ;initialize QuickDraw
  654.         _InitFonts        ;initialize the font manager
  655.         _InitCursor        ;get the arrow cursor
  656.         _InitWindows        ;initialize the window manager
  657.  
  658.         _InitMenus        ;ditto for menus
  659.         
  660.         CLR.L    -(SP)        ;our recovery proc is  NIL
  661.         _InitDialogs        ;initialize dialogs
  662.         _TEInit            ;and text edit, too
  663.  
  664. ; display the info box
  665.  
  666.         BSR    DisplayInfoBox
  667.  
  668. ; compute size of INIT resource to be added
  669.  
  670.         LEA    StartOfInit,A2
  671.         LEA    Start,A0
  672.         MOVE.L    A0,D0
  673.         SUB.L    A2,D0            ;compute size
  674.         MOVE.L    D0,D1            ;remember size
  675.  
  676. ; allocate a handle for the INIT resource
  677.  
  678.         DC.W    $A522            ;allocate a sysHeap handle        
  679.         BNE    NoInstall        ;if error, punt
  680.  
  681.         MOVE.L    A0,A3            ;remember it in A3
  682.  
  683. ; move in the code
  684.  
  685.         MOVE.L    A2,A0            ;souce is in A2
  686.         MOVE.L    (A3),A1            ;destination        
  687.         MOVE.L    D1,D0            ;set up size
  688.         _BlockMove            ;move it in
  689.  
  690. ; make sure it's not already installed
  691.  
  692.         CLR    -(SP)
  693.         _SetResLoad            ;resource loading off
  694.  
  695.         SUBQ    #4,SP
  696.         MOVE.L    InitRType,-(SP)
  697.         PEA    OpenPatchName
  698.         _GetNamedResource
  699.         MOVE.L    (SP)+,D0
  700.         BEQ    FindInitID
  701.  
  702. ; it's already there, so remove it
  703.  
  704.         MOVE.L    D0,-(SP)        ;push resource handle
  705.         
  706.         CLR.W    -(SP)
  707.         _UseResFile            ;use system file
  708.         
  709.         _RmveResource            ;remove it
  710.  
  711. ; compute the ID to use for the INIT resource
  712.  
  713. FindInitID
  714.         MOVEQ    #8,D3            ;start with ID = 8
  715.         
  716. INITIDLoop
  717.         SUBQ    #4,SP
  718.         MOVE.L    InitRType,-(SP)        ;push INIT
  719.         MOVE    D3,-(SP)        ;push the ID
  720.         _GetResource
  721.  
  722.         MOVE.L    (SP)+,D0        ;got it?
  723.         BEQ.S    AddTheInit        ;if not, use that ID
  724.  
  725.         ADDQ    #1,D3
  726.         CMP.W    #32,D3
  727.         BLT.S    INITIDLoop
  728.  
  729.         ST    -(SP)
  730.         _SetResLoad
  731.         
  732.         MOVEQ    #2,D0
  733. DoError        
  734.         MOVE    D0,-(SP)    ;remember entry code
  735.         
  736.         SUBQ    #2,SP
  737.         MOVE    D0,-(SP)
  738.  
  739.         CLR.L    -(SP)
  740.         
  741.         MOVE.W    CurApRefNum,-(SP)
  742.         _UseResFile
  743.         
  744.         _StopAlert
  745.         ADDQ    #2,SP
  746.  
  747.         SUBQ    #1,(SP)+    ;code 1?
  748.         BEQ.S    Reboot
  749.         
  750.         _ExitToShell
  751. NoInstall
  752.         MOVEQ    #3,D0
  753.         BRA.S    DoError
  754.         
  755. ; Simply reboot
  756.  
  757. Reboot
  758.         RESET
  759.  
  760. ; OK, the ID to use is in D3, so we can add the resource
  761.  
  762. AddTheInit
  763.         ST    -(SP)
  764.         _SetResLoad
  765.         
  766.         CLR    -(SP)
  767.         _UseResFile            ;use the system file
  768.         
  769.         MOVE.L    A3,-(SP)        ;push the handle
  770.         MOVE.L    InitRType,-(SP)        ;push INIT
  771.         MOVE.W    D3,-(SP)        ;push the ID
  772.  
  773.         PEA    OpenPatchName        ;push the name
  774.         _AddResource
  775.         
  776.         SUBQ    #2,SP
  777.         _ResError
  778.         TST.W    (SP)+
  779.         BNE.S    NoInstall
  780.  
  781. ; set the attributes
  782.  
  783.         MOVE.L    A3,-(SP)        ;push the resource
  784.         MOVE    #82,-(SP)        ;sysHeap,locked, changed
  785.         _SetResAttrs            ;set default attributes
  786.  
  787. ; write it out then update the resFile
  788.  
  789.         MOVE.L    A3,-(SP)
  790.         _WriteResource
  791.  
  792.         SUBQ    #2,SP
  793.         _ResError
  794.         MOVE    (SP)+,D0
  795.         BNE    NoInstall
  796.         
  797.         CLR.W    -(SP)
  798.         _UpdateResFile
  799.         
  800.         SUBQ    #2,SP
  801.         _ResError
  802.         MOVE    (SP)+,D0
  803.         BNE    NoInstall
  804.  
  805.  
  806.  
  807. ; better flush all the volumes
  808.  
  809.         MOVE.L    VCBQueue+2,D0
  810.         SUB.W    #80,SP
  811.         MOVE.L    SP,A0
  812. FlushLoop
  813.         MOVE.L    D0,A1
  814.         CLR.L    IOFileName(A0)
  815.         MOVE.W    78(A1),IOVRefNum(A0)
  816.         _FlushVol
  817.  
  818.         MOVE.L    (A1),D0
  819.         BNE.S    FlushLoop
  820.  
  821.         ADD.W    #80,SP
  822.  
  823. SuccessExit        
  824.  
  825.         MOVEQ    #1,D0
  826.         BRA    DoError
  827.  
  828. ReleaseIt
  829.         BRA.S    SuccessExit
  830.         
  831.         
  832. ; DisplayInfoBox puts up the initial dialog
  833.  
  834. DisplayInfoBox
  835.  
  836.         SUBQ    #4,SP            ;make space for result
  837.         MOVE    #1,-(SP)        ;dialog ID = 1
  838.         CLR.L    -(SP)            ;allocate window in heap
  839.  
  840.         MOVEQ    #-1,D0
  841.         MOVE.L    D0,-(SP)        ;frontmost window
  842.         _GetNewDialog            ;make it the dialog
  843. WarnSTLoop
  844.         CLR.L    -(SP)            ;no filterProc
  845.         PEA    -200(A5)        ;place for result
  846.         _ModalDialog            ;let Bruce fetch events
  847.         
  848.         MOVE.W    -200(A5),D0        ;get result
  849.         SUBQ    #1,D0
  850.         BEQ.S    WarnOK            ;if 1, its OK
  851.         SUBQ    #1,D0            ;cancel?
  852.         BNE.S    WarnSTLoop        ;if not, loop
  853.         
  854.         _DisposDialog
  855.         ADDQ    #4,SP
  856.         _ExitToShell
  857.         
  858. WarnOK
  859.         _DisposDialog
  860.         RTS
  861.         
  862.  
  863. ; strings, etc
  864.  
  865. InitRType
  866.         DC.B    'INIT'
  867. OpenPatchName
  868.  
  869.         DC.B    9,'OpenPatch'
  870.  
  871.                 
  872.         
  873.  
  874.  
  875.